/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package starfox;

import java.util.ArrayList;
import java.util.Iterator;
import util.Botao;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.Music;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Sound;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.state.transition.FadeInTransition;
import org.newdawn.slick.state.transition.FadeOutTransition;
import starfox.personagens.Andross;
import starfox.personagens.Arwing;
import starfox.personagens.InimigoSet1;
import starfox.personagens.InimigoSet2;
import starfox.personagens.InimigoSet3;
import starfox.personagens.Tile;
import starfox.personagens.TiroInimigo1;
import starfox.personagens.TiroInimigo3;
import starfox.personagens.TiroPersonagem;
import starfox.StarFox;
import util.JanelaRecordes;
import util.Recorde;

/**
 *
 * @author Lucas
 */
public class GamePlayState extends BasicGameState {
    //Número do estado
    int stateID = 1;

    //Passo de escala
    float scaleStep = 0.0005f;

    //Escala dos botões
    float continuarScale = 1;
    float sairScale = 1;

    //Mostra se o jogo está pausado
    boolean paused;

    //Imagens
    Image background = null;
    Image pause = null;
    Botao continuar = null;
    Botao sair = null;

    //Personagens
    Arwing arw = null;
    Andross and = null;
    ArrayList<InimigoSet1> inimigos1 = new ArrayList<InimigoSet1>();
    InimigoSet1 inimigo1 = null;
    ArrayList<InimigoSet2> inimigos2 = new ArrayList<InimigoSet2>();
    InimigoSet2 inimigo2 = null;
    ArrayList<InimigoSet3> inimigos3 = new ArrayList<InimigoSet3>();
    InimigoSet3 inimigo3 = null;

    TiroPersonagem tp = null;
    TiroInimigo1 t1 = null;
    TiroInimigo3 t3 = null;
    Tile tile = null;

    //Atributos para pegar a posição do mouse, botões do teclado etc
    Input input = null;
    int mouseX;
    int mouseY;

    //Variáveis para saber qual botao destacar quando o jogo for pausado
    boolean sobreContinuar = false;
    boolean sobreSair = false;

    //Música
    Music musica = null;
    //Efeito sonoro de explosão
    Sound explosao = null;

    GamePlayState( int stateID )
    {
       this.stateID = stateID;
    }

    @Override
    public int getID() {
        return stateID;
    }

    //Carregar as imagens, sons e personagens
    @Override
    public void init(GameContainer arg0, StateBasedGame arg1) throws SlickException {
        background = new Image("imagens/Espaço 2.jpg");
        pause = new Image("imagens/Pause.png");

        paused = false;
        
        musica = new Music("music/Corneria.ogg");
        explosao = new Sound("music/explosion-02.wav");

        Image botoes = new Image("imagens/botoes pause.png");
        continuar = new Botao(280, 248, botoes, 0, 0, 240, 38);
        sair = new Botao(348, 320, botoes, 69, 39, 104, 38);

        //Criar o chefe
        and = new Andross();
        
        //Criar o personagem
        arw = new Arwing();

        //Criar inimigos nas devidas posições
        for(int i=0; i<5; i++){
            inimigos1.add(new InimigoSet1(-(i+1)*200));
            inimigos2.add(new InimigoSet2(800 + i*200));
            inimigos3.add(new InimigoSet3(50 + i*150));
        }
    }

    //Reiniciar o jogo com novos elementos (inimigos, chefe, nave etc)
    public void reset() throws SlickException{
        paused = false;
        
        arw = new Arwing();
        and = new Andross();

        inimigos1 = new ArrayList<InimigoSet1>();
        inimigos2 = new ArrayList<InimigoSet2>();
        inimigos3 = new ArrayList<InimigoSet3>();
        
        for(int i=0; i<5; i++){
            inimigos1.add(new InimigoSet1(-(i+1)*200));
            inimigos2.add(new InimigoSet2(800 + i*200));
            inimigos3.add(new InimigoSet3(50 + i*150));
        }

        inimigo1 = null;
        inimigo2 = null;
        inimigo3 = null;

        tp = null;
        t1 = null;
        t3 = null;
        tile = null;
    }

    //Renderizar as imagens
    @Override
    public void render(GameContainer arg0, StateBasedGame arg1, Graphics g) throws SlickException {
        background.draw();
        
        and.render();
        arw.render();

        for(InimigoSet1 i : inimigos1)
            i.render();

        for(InimigoSet2 i : inimigos2)
            i.render();

        for(InimigoSet3 i : inimigos3)
            i.render();

        if(paused){
            pause.draw();
            continuar.draw();
            sair.draw();
        }
        
        //Desenhar a pontuação e o número de vidas na tela
        g.drawString("Pontuação: " + arw.getPontuacao() + " Vidas: " + arw.getVidas(), 550, 20);
    }

    //Atualizar o estado
    @Override
    public void update(GameContainer gc, StateBasedGame sb, int delta) throws SlickException {
        input = gc.getInput();
        mouseX = input.getMouseX();
        mouseY = input.getMouseY();

        //Se o mouse está sobre um dos botões
        sobreContinuar = false;
        sobreSair = false;
        
        //Tocar a música
        if(!musica.playing()) musica.play();

        /*Se o personagem não tem mais vidas, terminar o jogo
         * e passar a pontuação para o GameOverStateLose.*/
        if(arw.getVidas() == 0){
            explosao.play();
            musica.stop();
            GameOverStateLose.setPontuacao(arw.getPontuacao());
            sb.enterState(StarFox.GAMEOVERSTATELOSE);
            reset();
        }

        //Se o jogador apertou ESC, pausar ou despausar o jogo
        if(input.isKeyPressed(Input.KEY_ESCAPE))
        {
            if(!paused)
                paused = true;
            else
                paused = false;
        }
        
        //Se o jogo estiver pausado, mostra os botões e verifica se o mouse está por cima deles
        if(paused){
            if((mouseX >= continuar.getX() && mouseX <= continuar.getX() + continuar.getImageWidth()) &&
               (mouseY >= continuar.getY() && mouseY <= continuar.getY() + continuar.getImageHeight()))
                        sobreContinuar = true;
            else if((mouseX >= sair.getX() && mouseX <= sair.getX() + sair.getImageWidth()) &&
                    (mouseY >= sair.getY() && mouseY <= sair.getY() + sair.getImageHeight()))
                        sobreSair = true;

            if(sobreContinuar){
                if(continuar.getScale() < 1.05f)
                    continuar.changeScale(Botao.scaleStep*delta);
                if(input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON)){
                    paused = false;
                    continuar.setScale(1);
                }
            }
            else
                if(continuar.getScale() > 1.0f)
                    continuar.changeScale(-Botao.scaleStep*delta);

            if(sobreSair){
                if(sair.getScale() < 1.05f)
                    sair.changeScale(Botao.scaleStep*delta);
                if(input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON)){
                    sb.enterState(StarFox.MAINMENUSTATE, new FadeOutTransition(), new FadeInTransition());
                    sair.setScale(1);
                    reset();
                    musica.stop();
                }
            }
            else
                if(sair.getScale() > 1.0f)
                    sair.changeScale(-Botao.scaleStep*delta);
        }
        //Senão, atualizar o jogo normalmente
        else{
            arw.update(gc, delta);

            //Verificar se o tiro da nave atingiu algum inimigo do primeiro set
            for(Iterator<InimigoSet1> i1 = inimigos1.iterator(); i1.hasNext();){
                inimigo1 = i1.next();
                for(Iterator<TiroPersonagem> it = arw.getTiros().iterator(); it.hasNext();){
                    tp = it.next();
                    if(tp.getCaixaColisao().colisao(inimigo1.getCaixaColisao())){
                            i1.remove();
                            it.remove();
                            explosao.play();
                            arw.aumentarPontuacao(50);
                        }
                }
                //Verificar se um tiro do inimigo atingiu a nave
                for(Iterator<TiroInimigo1> it1 = inimigo1.getTiros().iterator(); it1.hasNext();){
                    t1 = it1.next();
                    if(t1.getCaixaColisao().colisao(arw.getCaixaColisao()) && arw.isCollidable()){
                            arw.setCollidable(false);
                            arw.diminuiVidas();
                            it1.remove();
                    }
                }
                //Se o inimigo do 1º set estiver na tela, atualizá-lo
                if(inimigo1.getPos().x <= 800)
                    inimigo1.update(delta);
                //Senão, removê-lo da ArrayList
                else
                    i1.remove();
            }
            //Se não há mais inimigos no primeiro set, mandar o segundo
            if(inimigos1.isEmpty()){
                //Idem primeiro set
                for(Iterator<InimigoSet2> i2 = inimigos2.iterator(); i2.hasNext();){
                    inimigo2 = i2.next();
                    for(Iterator<TiroPersonagem> it = arw.getTiros().iterator(); it.hasNext();){
                        tp = it.next();
                        if(tp.getCaixaColisao().colisao(inimigo2.getCaixaColisao())){
                            i2.remove();
                            it.remove();
                            explosao.play();
                            arw.aumentarPontuacao(100);
                        }
                    }
                    for(Iterator<TiroInimigo1> it1 = inimigo2.getTiros().iterator(); it1.hasNext();){
                        t1 = it1.next();
                        if(t1.getCaixaColisao().colisao(arw.getCaixaColisao()) && arw.isCollidable()){
                            arw.setCollidable(false);
                            arw.diminuiVidas();
                            it1.remove();
                        }
                    }
                    if(inimigo2.getPos().x > 0-inimigo2.getWidth())
                        inimigo2.update(delta);
                    else
                        i2.remove();
                }
            }
            //Se não há mais inimigos no segundo set, mandar o terceiro
            if(inimigos2.isEmpty()){
                //Idem primeiro e segundo sets
                for(Iterator<InimigoSet3> i3 = inimigos3.iterator(); i3.hasNext();){
                    inimigo3 = i3.next();
                    for(Iterator<TiroPersonagem> it = arw.getTiros().iterator(); it.hasNext();){
                        tp = it.next();
                        if(tp.getCaixaColisao().colisao(inimigo3.getCaixaColisao())){
                            i3.remove();
                            it.remove();
                            explosao.play();
                            arw.aumentarPontuacao(200);
                        }
                    }
                    for(Iterator<TiroInimigo3> it3 = inimigo3.getTiros().iterator(); it3.hasNext();){
                        t3 = it3.next();
                        if(t3.getCaixaColisao().colisao(arw.getCaixaColisao()) && arw.isCollidable()){
                            arw.setCollidable(false);
                            arw.diminuiVidas();
                            it3.remove();
                        }
                    }
                    if(inimigo3.getPos().x <= 800)
                        inimigo3.update(delta, arw);
                    else
                        i3.remove();
                }
            }
            //Se o terceiro set estiver vazio, manda o chefe
            if(inimigos3.isEmpty()){
                //Se o chefe estiver vivo, atualizá-lo
                if(and.isVivo()) and.update(delta, arw);
                //Senão, terminar o jogo e passar a pontuação para o GameOverStateWin
                else {
                    explosao.play();
                    musica.stop();
                    GameOverStateWin.setPontuacao(arw.getPontuacao());
                    sb.enterState(StarFox.GAMEOVERSTATEWIN);
                    reset();
                }
            }
        }
    }
}